package org.snail.common;

import org.apache.log4j.Logger;
import org.snail.constant.HolidayConstant;
import org.snail.constant.WorkSheetConstant;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 日期工具类
 * Created by WJ on 2017/11/14.
 */
public class DateUtils {

    private static Logger LOGGER = Logger.getLogger(DateUtils.class);

    public static final String TIME_WITH_MINUTE_PATTERN = "HH:mm";

    public static final long DAY_MILLI = 24 * 60 * 60 * 1000; // 一天的MilliSecond

    /**
     * 将Excel
     */

    /**
     * 要用到的DATE Format的定义
     */
    public static String DATE_FORMAT_DATEONLY = "yy-MM-dd"; // 年/月/日
    public static SimpleDateFormat sdfDateOnly = new SimpleDateFormat(DateUtils.DATE_FORMAT_DATEONLY);
    public static final SimpleDateFormat LONG_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM-dd HH:mm");
    public static final SimpleDateFormat DATE_FORMAT_TIME = new SimpleDateFormat("HH:mm:ss");
    public static final SimpleDateFormat HM_FORMAT = new SimpleDateFormat("HH:mm");
    public static final SimpleDateFormat HOLIDAY_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    /**
     * 根据日期格式字符串解析日期字符串
     *
     *
     * @param str
     * 日期字符串
     * @param parsePattern
     * 日期格式字符串
     * @return 解析后日期
     * @throws ParseException
     */
    public static Date parseDate(String str, SimpleDateFormat parsePattern) throws ParseException {
        return parsePattern.parse(str);
    }

    /**
     * yyyy-MM-dd HH:mm:ss 传入日期
     *
     * @param date
     * @return
     */
    public static String getReqDateStr(Date date) {
        return LONG_DATE_FORMAT.format(date);
    }

    /**
     * 比较日期大小
     *
     * @param comDate
     * @param toComDate
     * @return
     */
    public static boolean dateCompare(Date comDate, Date toComDate) {
        boolean comResult = false;

        if (comDate.after(toComDate)) {
            comResult = true;
        }
        return comResult;
    }

    public static Long countTime(Date d1, Date d2){
        long diff = 0;
        if (dateCompare(d1, d2)){
           diff = (d2.getTime() - d1.getTime())/(1000*60);
        }else {
            LOGGER.error("打卡数据不准确!下班时间早于上班时间");
        }
        return diff;

    }

    /**
     * 将1995/12/7 格式字符串转换为date
     * @param ymdStr
     * @return test
     */
    public static Date stringToDate(String ymdStr,SimpleDateFormat simpleDateFormat ){
        Date stringChangeDate = null;
        try {
            stringChangeDate = simpleDateFormat.parse(ymdStr);
        } catch (ParseException e) {
            LOGGER.error("char turn to Date fail!", e);
        }
        return stringChangeDate;
    }

    public static Date stringToDate(String ymdStr){
        SimpleDateFormat sdf  = new SimpleDateFormat("yyyy/MM/dd");
        Date stringChangeDate = null;
        try {
            stringChangeDate = sdf.parse(ymdStr);
        } catch (ParseException e) {

        }
        return stringChangeDate;
    }

    /**
     * 将"04-十二月-2015" 的字符串转换为"1995/12/7"
     * @param oldStr
     * @return
     */
    public static String parseStr(String oldStr){
        Map<String,String> map = new HashMap<String,String>();
        map.put("一月","01");
        map.put("二月","02");
        map.put("三月","03");
        map.put("四月","04");
        map.put("五月","05");
        map.put("六月","06");
        map.put("七月","07");
        map.put("八月","08");
        map.put("九月","09");
        map.put("十月","10");
        map.put("十一月","11");
        map.put("十二月","12");
        String[] strArr = oldStr.split("-");
        String changeStr = strArr[2]+"/"+map.get(strArr[1])+"/"+strArr[0];
        return changeStr;
    }

    /**
     * 根据系统当前时间判断月份，截取出适合考勤的表的格式
     * @return  monthCondition 月份条件
     */
    public static String create_yy_mm(){
        Calendar cal = Calendar.getInstance();
        String month = cal.get(Calendar.MONTH) + 1 + "";

        String year =cal.get(Calendar.YEAR) + "";
        String year2 = year.substring(2);    //截取年份后面两位数字
        String monthCondition = year2 + "-" + month;
        return monthCondition;
    }

    //获取当前时间
    public static Date getCurrentTime(Integer addHour){
        //因为mongoDB中时区和中国时区相差8个小时，所以获取当前时间后加上8小时
        long currentTime = System.currentTimeMillis();
        currentTime += addHour*60*60*1000;
        return new Date(currentTime);

    }


    //毫秒转 时分
    public static String msTransHours(long ms) {

        int ss = 1000;
        int mi = ss * 60;
        int hh = mi * 60;
        int dd = hh * 24;

        long day = ms / dd;
        long hour = (ms - day * dd) / hh;
        long minute = (ms - day * dd - hour * hh) / mi;
        long second = (ms - day * dd - hour * hh - minute * mi) / ss;
        long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss;

        String strDay = day < 10 ? "0" + day : "" + day; //天
        String strHour = hour < 10 ? "0" + hour : "" + hour;//小时
        String strMinute = minute < 10 ? "0" + minute : "" + minute;//分钟
        String strSecond = second < 10 ? "0" + second : "" + second;//秒
        String strMilliSecond = milliSecond < 10 ? "0" + milliSecond : "" + milliSecond;//毫秒
        strMilliSecond = milliSecond < 100 ? "0" + strMilliSecond : "" + strMilliSecond;

        return strHour + ":" + strMinute;
    }
//
//    /**
//     * 获取指定年月的工作天数包含法定节假日
//     * @param year
//     * @param month
//     * @return
//     */
//    public static List<Date> getDates(int year, int month) {
//        List<Date> dates = new ArrayList<Date>();
//
//        Calendar cal = Calendar.getInstance();
//        cal.set(Calendar.YEAR, year);
//        cal.set(Calendar.MONTH, month - 1);
//        cal.set(Calendar.DATE, 1);
//        while (cal.get(Calendar.YEAR) == year && cal.get(Calendar.MONTH) < month) {
//            int day = cal.get(Calendar.DAY_OF_WEEK);
//
//            if (!(day == Calendar.SUNDAY || day == Calendar.SATURDAY)) {
//                dates.add((Date) cal.getTime().clone());
//            }
//            cal.add(Calendar.DATE, 1);
//        }
//        return dates;
//
//    }

    /**
     * 将字符串 2018-08-09 转化为 2018-08
     * @param dateStr
     * @return
     */
    public static String transDateStringToMY(String dateStr){
        String[] strArr = dateStr.split("-");
        String transDate = strArr[0]+"-"+strArr[1];
        return transDate;
    }

    /**
     * 计算工作时长
     * @param workTime 上班打卡时间
     * @param offTime  下班打卡时间
     * @return 返回相差分钟数
     */
    public static int countWorkMin(String workTime, String offTime) throws ParseException {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat simpleFormat = new SimpleDateFormat("yy-MM-dd HH:mm");
        int minutes = 0;
        if (StringUtils.isEmpty(workTime) || StringUtils.isEmpty(offTime)) {
            return minutes;
        }
        if(offTime.contains("次日")){
            String year = offTime.split("次日")[0];
            String hour = offTime.split("次日")[1];
            String over = year.trim()+" "+hour.trim();
            cal.setTime(simpleFormat.parse(over));
            cal.add(Calendar.DATE,1);
            offTime = simpleFormat.format(cal.getTime());
        }

        long from = 0;
        long to = 0;
        try {
            from = simpleFormat.parse(workTime).getTime();
            to = simpleFormat.parse(offTime).getTime();
        } catch (Exception e) {
            LOGGER.error("时间转换错误！", e);
        }
        minutes = (int) ((to - from)/(1000 * 60));
        return minutes ;
    }

    /**
     * 将打卡时间转变成date类型，便于时间计算
     * @param  dateStr :考勤excel中的日期 18-07-01 星期日
     * @param punchTime 上下班打卡时间   上班打卡时间：09:14
     *                  下班打卡时间类似上班打卡时间，但是存在加班到次日的情况 例:次日 03:06
     * @return punchTime 的date类型
     */
    public static Date formatPunchTimeToDate(String punchTime, String dateStr) throws ParseException {
        if (null == punchTime || null == dateStr) {
            return null;
        }
        String workDateStr = "20" + dateStr.split(" ")[0] + " " + punchTime;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date offTime = new Date();
        if (punchTime.contains(WorkSheetConstant.NEXT_DAY)) {
            Calendar calendar = new GregorianCalendar();
            calendar.setTime(offTime);
            calendar.add(calendar.DATE,1); //含有次日的函数需要加一天
            offTime = calendar.getTime();
        }else {
            offTime = simpleDateFormat.parse(workDateStr);
        }
        return offTime;
    }


    /**
     *  将考勤日期取出转换为 2018-07-11 的日期格式
     * @param dateStr  18-07-11 星期三
     * @return
     * @throws ParseException
     */
    public static Date parseDateStrToDate(String dateStr) throws ParseException {
        Date result = null;
        //dateStr 18-05-12 星期六，转换成date类型
        if(!StringUtils.isEmpty(dateStr)&&dateStr.length()>=12) {
            String dateDemo = dateStr.split(" ")[0];         // 将18-05-12取出
            String datePattern = "20" + dateDemo;             //虽然有些简单粗暴，但是还是将代码强行转为2018-05-12
            SimpleDateFormat strToDate = new SimpleDateFormat("yyyy-MM-dd");

            result = strToDate.parse(datePattern);
        }
        return result;
    }

    /**
     * 计算 07-25  到 07-26之间相差的天数
     * 传入的参数为"事假07-25 09:00到07-26 18:00 15.5"
     * @param approval
     * @throws ParseException
     */
    public static Long fewDay(String approval) throws ParseException{
        long day = 0;
        String[] strTemp = approval.split(" ");
        String startTime = strTemp[0].substring(strTemp[0].length()-5);
        String endTime = strTemp[1].substring(strTemp[1].length()-5);
        SimpleDateFormat sdf = new SimpleDateFormat("mm-dd");
        Date sd1 =sdf.parse(startTime);
        Date sd2 =sdf.parse(endTime);
        day = (sd2.getTime() - sd1.getTime())/(1000*3600*24);
        return day;
    }

    /**
     * 计算两个时间相差多少分钟
     * @param str1 "12:00"
     * @param str2 "13:00"
     * @return	60
     * @throws ParseException
     */
    public static Long countMinutes(String str1 , String str2) throws ParseException{
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        Long time = sdf.parse(str2).getTime() - sdf.parse(str1).getTime();
        return time/1000/60;
    }

    /********************计算指定月份的法定工作日*************************/

    /**
     * 计算法定工作日
     * 1.计算当月一共多少天
     * 2.去除法定节假日
     * 3.去除周末休息(不包含补班)
     * @param date
     * @return
     */

    public static int legalWorkingDay(Date date){
        int days = getDaysOfMonth(date);
        int result = days;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        for(int i=1;i<=days;i++){
            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH)+1;
            calendar.set(year,month-1,i);
            if(isRest(calendar.getTime())){
                result--;
            }

        }
        return result;
    }

    /**
     * 判断给定日期是是否为法定节假日或者周末休息
     * @param date 给定日期
     * @return
     */
    public static boolean isRest(Date date){
        boolean result = false;
        String dateStr = HOLIDAY_FORMAT.format(date);
        Map<Integer,Map<String,List<String>>> restMap =  HolidayConstant.getRest();
        for(Map<String,List<String>> map : restMap.values()){
            Collection<List<String>> list = map.values();
            for(List<String> l : list){
                if(l.contains(dateStr)){
                    result =true;
                    return result;
                }
            }
        }
        return result;
    }

    /**
     *  获取给定日期一个月天数
     */

    public  static int getDaysOfMonth(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /********************计算指定月份的法定工作日 end*************************/

}
